package cc.rengu.igas.opms.core.service.trans.gateway;

import cc.rengu.igas.acct.facade.bean.MchtAdjustDetail;
import cc.rengu.igas.acct.facade.request.VirtAcctMultiMchntAdjustRequest;
import cc.rengu.igas.momp.facade.base.Header;
import cc.rengu.igas.momp.facade.bean.ClaimCouponMcInfoBean;
import cc.rengu.igas.momp.facade.request.ClaimCouponRequest;
import cc.rengu.igas.momp.facade.request.ComboPaymentReversalRequest;
import cc.rengu.igas.opms.common.constant.OpmsParamConstant;
import cc.rengu.igas.opms.common.constant.OpmsServiceConstant;
import cc.rengu.igas.opms.common.enums.RespCodeEnum;
import cc.rengu.igas.opms.facade.request.CpcnResultNoticeRequest;
import cc.rengu.igas.opms.facade.response.CpcnResultNoticeResponse;
import cc.rengu.igas.share.common.constant.ShareParamConstant;
import cc.rengu.igas.share.common.enums.FeeTypeEnum;
import cc.rengu.igas.share.common.enums.SettleAcctTypeEnum;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.share.core.model.MchntAcctInfo;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.realize.CsmcService;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.CsmcServiceImpl;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.base.BizBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.PayOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.UserOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.PayOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.UserOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.MchntOrderInfo;
import cc.rengu.oltp.service.common.entity.PayOrderInfo;
import cc.rengu.oltp.service.common.entity.UserOrderInfo;
import cc.rengu.oltp.service.common.enums.*;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.RiskMonitorInfo;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.OrderService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.OrderServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 中金企业网关支付结果通知
 * T00PM063
 * 中金网关->open->支付通道->收银台
 *
 * @author fuyp
 * @date 2020/7/21.
 */
public class CpcnResultNoticeService extends BizBaseService {
    @Override
    protected Object beforeBizProcess() throws Exception {
        CpcnResultNoticeRequest cpcnResultNoticeRequest = new CpcnResultNoticeRequest();
        ConvertUtil.convertOutput(cpcnResultNoticeRequest);
        return cpcnResultNoticeRequest;
    }

    @Override
    protected BizResponse callBizService(Object request) throws Exception {

        BizResponse<CpcnResultNoticeResponse> response = new BizResponse<>();
        CpcnResultNoticeResponse cpcnResultNoticeResponse = new CpcnResultNoticeResponse();
        int iReturnCode = 0;

        CpcnResultNoticeRequest cpcnResultNoticeRequest = (CpcnResultNoticeRequest) request;
        String respCode = cpcnResultNoticeRequest.getOrderStatus(); //状态: 10=未支付 20=已支付
        String bankNotificationTime = cpcnResultNoticeRequest.getBankNotificationTime(); //支付平台收到银行通知时间
        OrderService orderService = new OrderServiceImpl();

        /*根据中金订单号查询支付订单表*/
        PayOrderInfoMapper payOrderInfoMapper = new PayOrderInfoMapperImpl();
        List<PayOrderInfo> oriPayOrderInfoList = payOrderInfoMapper.selectPayOrderInfoBySysSeqNum(cpcnResultNoticeRequest.getHeader().getInstId(), cpcnResultNoticeRequest.getPaymentNo());
        List<PayOrderInfo> payOrderInfoList = oriPayOrderInfoList.stream().filter(item -> item.getMsgDstId().equals(ChannelEnum.CPCN.getChannelType())).collect(Collectors.toList());
        if (payOrderInfoList.size() != 1) {
            rglog.error("机构<{}>没有对应的中金订单号<{}>信息", cpcnResultNoticeRequest.getHeader().getInstId(), cpcnResultNoticeRequest.getPaymentNo());
            throw new BizException("36", "与原交易信息不符");
        }
        PayOrderInfo payOrderInfo = payOrderInfoList.get(0);

        /*判断支付订单是否终态*/
        rglog.debug("支付订单交易状态:<{}>,业务状态:<{}>", payOrderInfo.getTransStatus(), payOrderInfo.getBizStatus());
        if (TransStatusEnum.TRANS_SUCC.getStatus().equals(payOrderInfo.getTransStatus()) &&
                (BizStatusEnum.FINISH.getStatus().equals(payOrderInfo.getBizStatus()) ||
                        BizStatusEnum.REFUND.getStatus().equals(payOrderInfo.getBizStatus()) ||
                        BizStatusEnum.PART_REFUND.getStatus().equals(payOrderInfo.getBizStatus()) ||
                        BizStatusEnum.CONFIRM.getStatus().equals(payOrderInfo.getBizStatus()))) {
            rglog.error("订单已成功，不处理直接返回结果");
            cpcnResultNoticeResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            cpcnResultNoticeResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            response.setResult(cpcnResultNoticeResponse);
            response.setRspSysId(AppParamConstant.IGAS);
            response.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
            response.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
            return response;
        }

        /*根据中金订单号查询用户订单表*/
        UserOrderInfoMapper userOrderInfoMapper = new UserOrderInfoMapperImpl();
        UserOrderInfo userOrderInfo = userOrderInfoMapper.selectUserOrderInfoByPrimaryKey(cpcnResultNoticeRequest.getHeader().getInstId(), cpcnResultNoticeRequest.getPaymentNo());
        if (userOrderInfo == null) {
            rglog.error("机构<{}>没有对应的用户订单号<{}>信息", cpcnResultNoticeRequest.getHeader().getInstId(), cpcnResultNoticeRequest.getPaymentNo());
            throw new BizException("36", "与原交易信息不符");
        }

        /*根据系统流水号查询商户订单表*/
        MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
        List<MchntOrderInfo> mchntOrderInfoList = mchntOrderInfoMapper.selectMchntOrderInfoBySysSeqNum(userOrderInfo.getInstId(), userOrderInfo.getSysSeqNum());

        /*根据响应信息判断原支付订单是否成功*/
        rglog.debug("原支付订单响应码:<{}>", respCode);
        if ("20".equals(respCode)) {

            /*支付成功,更新当前支付订单状态*/
            userOrderInfo.setOrderStatus(OrderStatusEnum.FINISH.getStatus());
            userOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            userOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
                mchntOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
                mchntOrderInfo.setRealSettleAmt(AmountUtil.subtraction(mchntOrderInfo.getRealSettleAmt(), mchntOrderInfo.getCustomerMarketAmt()));
                mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            }

            payOrderInfo.setPayerAcctType(AcctTypeEnum.OTHER_DEBIT.getAcctType());
            payOrderInfo.setPayerAcctInfo(cpcnResultNoticeRequest.getPayerAccountNumber());
            payOrderInfo.setTransStatus(TransStatusEnum.TRANS_SUCC.getStatus());
            payOrderInfo.setBizStatus(BizStatusEnum.FINISH.getStatus());
            payOrderInfo.setSettleDate(bankNotificationTime.substring(0, 8));
            payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));

            //非购买卡券的交易的计算商户手续费并调用营销获取商户的手续费营销
            rglog.trace("流程日志-非购买卡券的交易的计算商户手续费并调用营销获取商户的手续费营销....");
            if (!"00".equals(mchntOrderInfoList.get(0).getBizSceneType()) && !"02".equals(mchntOrderInfoList.get(0).getBizSceneType())) {

                rglog.debug("非购买卡券的交易的计算商户手续费并调用营销获取商户的手续费营销....");
                // 计算商户手续费
                List<PayOrderInfo> mompPayOrderList = oriPayOrderInfoList.stream().filter(item -> ShareParamConstant.MOMP_COMBO_PAY.equals(item.getDstTxnNum())).collect(Collectors.toList());
                String mompCallIndex = "0";
                if (!mompPayOrderList.isEmpty()) {
                    mompPayOrderList = mompPayOrderList.stream().sorted(Comparator.comparing(PayOrderInfo::getDstCallIndex).reversed()).collect(Collectors.toList());
                    String dstCallIndex = mompPayOrderList.get(0).getDstCallIndex();
                    mompCallIndex = String.valueOf(Integer.parseInt(dstCallIndex) + 1);
                }
                MchntService mchntService = new MchntServiceImpl();
                boolean calcResult = mchntService.calcMchntFee(mchntOrderInfoList, FeeTypeEnum.OTHER_BANK_DR_CARD.getFeeType());
                if (!calcResult) {
                    rglog.info("手续费计算失败，交易终止");
                    ConvertUtil.convertOutput(cpcnResultNoticeResponse);
                    response.setResult(cpcnResultNoticeResponse);
                    response.setRspSysId(AppParamConstant.IGAS);
                    response.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
                    response.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
                    return response;
                }
            }

            //更新用户订单，商户订单，支付订单的状态
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
                rglog.error("更新支付订单状态失败");
                throw new BizException(RespCodeEnum.UPDATE_ORDER_ERROR.getRespCode(), RespCodeEnum.UPDATE_ORDER_ERROR.getRespDesc());
            }

            //购买卡券的交易领取卡券
            claimCoupon(mchntOrderInfoList);

            //商户入账-DO入账或记虚拟账户
            rglog.debug("商户入账判断:<{}>", mchntOrderInfoList.get(0).getRealSettleFlag());
            if (AppParamConstant.YES.equals(mchntOrderInfoList.get(0).getRealSettleFlag())) {
                //实时入账
                mchntRealTimeAccouting(mchntOrderInfoList);
                iReturnCode = asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0);
                if (0 != iReturnCode) {
                    rglog.error("提交交易结果异步通知给商户失败!");
                }
            } else {
                //异步记虚拟账
                virtAcctMultiMchntAdjust(userOrderInfo, mchntOrderInfoList, payOrderInfo);
            }


        } else if ("10".equals(respCode)) {

            /*更新订单表状态为业务处理中*/
            userOrderInfo.setOrderStatus(OrderStatusEnum.INIT.getStatus());
            userOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
            userOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
            userOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                mchntOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
                mchntOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
                mchntOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            }
            payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
            payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
            payOrderInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.updateOrderInfo(userOrderInfo, mchntOrderInfoList, payOrderInfo)) {
                rglog.error("更新订单表状态失败");
            }

            /*异步调用营销冲正*/
            //mompComboPayRevsal(mchntOrderInfoList, payOrderInfoList);
        }

        ConvertUtil.convertOutput(cpcnResultNoticeResponse);
        response.setResult(cpcnResultNoticeResponse);
        response.setRspSysId(AppParamConstant.IGAS);
        response.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        response.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return response;
    }


    @Override
    protected void afterBizProcess(BizResponse response) throws Exception {
        CpcnResultNoticeResponse cpcnResultNoticeResponse = (CpcnResultNoticeResponse) response.getResult();
        ConvertUtil.convertInput(cpcnResultNoticeResponse);
    }

    @Override
    protected RiskMonitorInfo getRiskMonitorInfo() {
        return null;
    }

    private PayOrderInfo convPayOrderInfo(UserOrderInfo userOrderInfo, String chanId, String destTxnNum) {
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(userOrderInfo, payOrderInfo);
        if (payOrderInfo.getOrderAmt() == null || payOrderInfo.getOrderAmt().isEmpty()) {
            payOrderInfo.setOrderAmt("0.00");
        }
        payOrderInfo.setMsgDstId(chanId);
        payOrderInfo.setDstCallIndex("0");
        payOrderInfo.setChannelSeqNum(payOrderInfo.getSysSeqNum() + payOrderInfo.getDstCallIndex());
        payOrderInfo.setChannelReconKey(payOrderInfo.getSysSeqNum() + payOrderInfo.getDstCallIndex());
        payOrderInfo.setDstTxnNum(destTxnNum);
        payOrderInfo.setPayType(PayTypeEnum.OTHER_BANK_CARD.getPayType());
        payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
        payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
        payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        return payOrderInfo;
    }

    /**
     * 商户实时入账
     *
     * @param mchntOrderInfoList 商户订单列表
     */
    private void mchntRealTimeAccouting(List<MchntOrderInfo> mchntOrderInfoList) throws Exception {

        if ("00".equals(mchntOrderInfoList.get(0).getBizSceneType())
                || "01".equals(mchntOrderInfoList.get(0).getBizSceneType())
                || "02".equals(mchntOrderInfoList.get(0).getBizSceneType())
                || "0".equals(mchntOrderInfoList.get(0).getFeeInputMode())) {
            rglog.info("购买卡券、担保支付、特殊费率的商户订单不支持实时入账");
            return;
        }

        /*获取渠道户*/
        CsmcService csmcService = new CsmcServiceImpl();
        String roleActualAcctNo = csmcService.getRoleActualAcctNo(mchntOrderInfoList.get(0).getInstId(), SettleAcctTypeEnum.DZ_SUBJECT.getSettleAcct(), null);
        if (StringUtil.isEmptyOrNull(roleActualAcctNo)) {
            rglog.error("获取渠道户信息失败，商户实时入账失败，转t1");
            return;
        }
        ChannelCallCfg channelCallCfg = new ChannelCallCfg();
        channelCallCfg.setCallIndex("0");
        channelCallCfg.setCallChannelId(ChannelEnum.ESB.getChannelType());
        channelCallCfg.setCallChannelTxn("00010000175500");
        int callIndex = Integer.parseInt(channelCallCfg.getCallIndex());
        int iReturnCode;
        //商户收支两线的标识
        char incomeFlag = '1';

        DubboService dubboService = new DubboServiceImpl();
        MchntService mchntService = new MchntServiceImpl();
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {

            if (AppParamConstant.NO.equals(mchntOrderInfo.getRealSettleFlag())) {
                rglog.error("商户订单非实时清算");
                return;
            }

            /*查询商户结算账户信息表，判断结算周期及结算账户类型*/
            MchntInfo mchntInfo;
            try {
                mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
                List<MchntAcctInfo> mchntAcctInfoList;
                /*判断是否独立维护资料的门店*/
                if ("11".equals(mchntInfo.getMchntType()) && AppParamConstant.NO.equals(mchntInfo.getIndependentDataFlag())) {
                    mchntAcctInfoList = mchntService.getMchntAcctInfo(mchntOrderInfo.getInstId(), mchntInfo.getChainMchntNo());
                } else {
                    mchntAcctInfoList = mchntService.getMchntAcctInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
                }
                Optional<MchntAcctInfo> mchntAcctInfoOpt = mchntAcctInfoList.stream().filter(item -> item.getBaseProdCode().equals(mchntOrderInfo.getBizProdCode()) && item.getFundType().equals("00")).findFirst();
                if (!mchntAcctInfoOpt.isPresent()) {
                    rglog.error("获取商户结算账户信息失败，商户实时入账失败，转t1");
                    return;
                }

                //收支两线商户取商户清算本金
                String mchntAmt;
                if (incomeFlag == mchntInfo.getMchntSettleMode().charAt(1)) {
                    mchntAmt = mchntOrderInfo.getRealSettleAmt();
                } else {
                    mchntAmt = mchntOrderInfo.getMchntSettleAmt();
                }

                //登记DO支付订单，若登记失败则跳过当前商户，当前商户不再实时记账转T1
                PayOrderInfo payOrderInfo = registerD0PayOrderInfo(mchntOrderInfo, roleActualAcctNo, AcctTypeEnum.BANK_ACCT.getAcctType(),
                        mchntAcctInfoOpt.get().getSettleAcctNo(), mchntAcctInfoOpt.get().getSettleAcctType(), channelCallCfg, String.valueOf(callIndex), mchntAmt);
                if (payOrderInfo == null) {
                    rglog.info("登记支付订单失败，当前商户不再实时记账转T1");
                    continue;
                }

                //TODO 由项目组实现该部分 调用D0实时清算，后调用AsynMchntD0AccoutingService根据清算结果进行处理
                iReturnCode = dubboService.asynCallDubboService("dubboService", "method", "request", "AsynMchntD0AccoutingService");
                if (iReturnCode != 0) {
                    rglog.error("异步d0入账服务注册失败！");
                }
                callIndex++;
            } catch (Exception e) {
                rglog.error(e.getMessage());
                rglog.error("商户实时入账异常:<{}>", e);
            }
        }
    }

    /**
     * 登记D0记账支付订单流水
     *
     * @param mchntOrderInfo 商户订单
     * @param payAcctNo      支付账号
     * @param payAcctType    支付账户类型
     * @param payeeAcctNo    收款账户
     * @param payeeAcctType  收款账户类型
     * @param channelCallCfg 通道服务调用配置
     * @param callIndex      调用序号
     * @return do支付订单
     */
    private PayOrderInfo registerD0PayOrderInfo(MchntOrderInfo mchntOrderInfo, String payAcctNo, String payAcctType, String payeeAcctNo, String payeeAcctType, ChannelCallCfg channelCallCfg, String callIndex, String mchntAmt) {

        OrderService orderService = new OrderServiceImpl();
        PayOrderInfo payOrderInfo = new PayOrderInfo();
        BeanUtil.beanCopy(mchntOrderInfo, payOrderInfo);
        payOrderInfo.setTxnNum(OpmsParamConstant.D0_ACCOUTING_TXN_NUM);
        try {
            /*系统流水号取下单交易的系统流水号*/
            payOrderInfo.setSysSeqNum(mchntOrderInfo.getSysSeqNum());
            payOrderInfo.setMsgDstId(channelCallCfg.getCallChannelId());
            if (callIndex != null) {
                payOrderInfo.setDstCallIndex(callIndex);
                payOrderInfo.setChannelSeqNum(mchntOrderInfo.getSysSeqNum() + callIndex);
                payOrderInfo.setChannelReconKey(GlobalEsbUtil.generateEsbSeqeuenceNumber(mchntOrderInfo.getInstId()));
            } else {
                payOrderInfo.setDstCallIndex(channelCallCfg.getCallIndex());
                payOrderInfo.setChannelSeqNum(mchntOrderInfo.getSysSeqNum() + channelCallCfg.getCallIndex());
                payOrderInfo.setChannelReconKey(GlobalEsbUtil.generateEsbSeqeuenceNumber(mchntOrderInfo.getInstId()));
            }
            payOrderInfo.setChannelBizType(ShareParamConstant.OTHER_SUB_SYS_ID_D0_REALTIME);
            payOrderInfo.setRealPayAmt(mchntAmt);
            payOrderInfo.setDstTxnNum(channelCallCfg.getCallChannelTxn());
            payOrderInfo.setPayType(PayTypeEnum.BANK_CARD.getPayType());
            payOrderInfo.setPayerAcctType(payAcctType);
            payOrderInfo.setPayerAcctInfo(payAcctNo);
            payOrderInfo.setPayeeAcctType(payeeAcctType);
            payOrderInfo.setPayeeAcctInfo(payeeAcctNo);
            payOrderInfo.setBizStatus(BizStatusEnum.PROCESSING.getStatus());
            payOrderInfo.setTransStatus(TransStatusEnum.TRANS_INIT.getStatus());
            payOrderInfo.setCreateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
            if (!orderService.registerOrderInfo(null, null, payOrderInfo)) {
                rglog.error("登记支付订单表失败,payOrderInfo=[{}]", JSON.toJSONString(payOrderInfo));
                return null;
            }
            return payOrderInfo;
        } catch (Exception e) {
            rglog.error(e.getMessage());
            return null;
        }
    }


    /*商户虚拟账户记账*/
    void virtAcctMultiMchntAdjust(UserOrderInfo userOrderInfo, List<MchntOrderInfo> mchntOrderInfoList, PayOrderInfo payOrderInfo) throws Exception {

        if ("00".equals(mchntOrderInfoList.get(0).getBizSceneType())
                || "01".equals(mchntOrderInfoList.get(0).getBizSceneType())
                || "02".equals(mchntOrderInfoList.get(0).getBizSceneType())
                || "0".equals(mchntOrderInfoList.get(0).getFeeInputMode())) {
            rglog.error("购买卡券交易或担保支付交易或特殊费率，不记商户虚拟账");
            int iReturnCode = asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0);
            if (0 != iReturnCode) {
                rglog.error("提交交易结果异步通知给商户失败!");
            }
            return;
        }

        OrderService orderService = new OrderServiceImpl();
        MchntService mchntService = new MchntServiceImpl();
        MchntInfo mchntInfo = null;
        DubboService dubboService = new DubboServiceImpl();
        String realPayAmt = "0.00";
        //商户收支两线的标识
        char incomeFlag = '1';
        try {
            VirtAcctMultiMchntAdjustRequest request = new VirtAcctMultiMchntAdjustRequest();
            cc.rengu.igas.acct.facade.base.Header header = new cc.rengu.igas.acct.facade.base.Header();
            ConvertUtil.convertOutput(header);
            header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
            header.setSrcSysId(AppParamConstant.SYS_ID);
            header.setBizType("00");
            header.setTxnNum("P01AT002");
            header.setVersion("1.0.0");
            header.setTraceNo(userOrderInfo.getSysSeqNum() + "0");
            header.setTransTime(DateUtil.getCurrentTime());
            header.setTransDate(DateUtil.getCurrentDate());
            request.setHeader(header);
            request.setAcctType("00");
            request.setDebitCreditFlag("C");
            List<MchtAdjustDetail> mchtAdjustDetailList = new ArrayList<>();
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                MchtAdjustDetail mchtAdjustDetail = new MchtAdjustDetail();
                mchtAdjustDetail.setUserType("00");
                mchntInfo = mchntService.getMchntInfo(mchntOrderInfo.getInstId(), mchntOrderInfo.getMchntNo());
                /*判断是否独立维护资料的门店*/
                if ("11".equals(mchntInfo.getMchntType()) && !AppParamConstant.YES.equals(mchntInfo.getIndependentDataFlag())) {
                    mchtAdjustDetail.setUserId(mchntInfo.getChainMchntNo());
                } else {
                    mchtAdjustDetail.setUserId(mchntInfo.getMchntNo());
                }
                /*收支两线的商户使用商户清算本金金额到虚拟账户记账，合并轧差的商户使用商户结算净额到虚拟账户记账*/
                rglog.info("当前商户:<{}>的结算模式:<{}>", mchntInfo.getMchntNo(), mchntInfo.getMchntSettleMode());
                if (incomeFlag == mchntInfo.getMchntSettleMode().charAt(1)) {
                    realPayAmt = AmountUtil.addition(realPayAmt, mchntOrderInfo.getRealSettleAmt());
                    mchtAdjustDetail.setTransAmt(mchntOrderInfo.getRealSettleAmt());
                } else {
                    realPayAmt = AmountUtil.addition(realPayAmt, mchntOrderInfo.getMchntSettleAmt());
                    mchtAdjustDetail.setTransAmt(mchntOrderInfo.getMchntSettleAmt());
                }
                //如果商户记虚拟账户的金额等于0则不记该商户的虚拟账户
                if (AmountUtil.compare("0", mchtAdjustDetail.getTransAmt()) == 0) {
                    continue;
                }
                mchtAdjustDetailList.add(mchtAdjustDetail);
            }
            if (mchtAdjustDetailList.isEmpty()) {
                int iReturnCode = asynnotify.transactionNotice("MchntTransNoticeService", 1, 0, 0);
                if (0 != iReturnCode) {
                    rglog.error("提交交易结果异步通知给商户失败!");
                }
                rglog.error("没有非D0的商户，不进行虚拟账户记账");
                return;
            }
            List<MchtAdjustDetail> mchtAdjustDetailListFinal = new ArrayList<>();
            /*按商户分组去重，累计求和*/
            Map<String, List<MchtAdjustDetail>> groupByUserId = mchtAdjustDetailList.stream().collect(Collectors.groupingBy(MchtAdjustDetail::getUserId));
            for (Map.Entry<String, List<MchtAdjustDetail>> entryUserId : groupByUserId.entrySet()) {
                String totalTransAmt = "0";
                String userId = entryUserId.getKey();
                List<MchtAdjustDetail> entryMchtAdjustDetailList = entryUserId.getValue();
                for (MchtAdjustDetail mchtAdjustDetail : entryMchtAdjustDetailList) {
                    totalTransAmt = AmountUtil.addition(totalTransAmt, mchtAdjustDetail.getTransAmt());
                }
                MchtAdjustDetail mchtAdjustDetail = new MchtAdjustDetail();
                mchtAdjustDetail.setUserType("00");//01-商户
                mchtAdjustDetail.setUserId(userId);
                mchtAdjustDetail.setTransAmt(totalTransAmt);
                mchtAdjustDetailListFinal.add(mchtAdjustDetail);
            }
            request.setMchtAdjustDetailList(mchtAdjustDetailListFinal);

            //登记虚拟账户支付订单
            PayOrderInfo acctPayOrderInfo = convPayOrderInfo(userOrderInfo, ChannelEnum.ACCT.getChannelType(), "P01AT002");
            acctPayOrderInfo.setTxnNum(payOrderInfo.getTxnNum());
            acctPayOrderInfo.setBizType(payOrderInfo.getBizType());
            acctPayOrderInfo.setRealPayAmt(realPayAmt);
            if (!orderService.registerOrderInfo(null, null, acctPayOrderInfo)) {
                rglog.error("登记虚拟账户记账支付订单失败");
                return;
            }

            //异步调起虚拟账户记账服务
            int iReturnCode = dubboService.asynCallDubboService(OpmsParamConstant.DUBBO_ACCT_VIRTACCT_SERVICE,
                    OpmsParamConstant.DUBBO_ACCT_VIRTACCTMULTIMCHNTADJUST, request, OpmsServiceConstant.ASYN_VIRTACCT_MULTIMCHNT_ADJUST_SERVICE);
            if (iReturnCode != 0) {
                rglog.error("异步虚拟账户记账服务注册失败！");
            } else {
                rglog.error("异步虚拟账户记账服务注册成功！");
            }
        } catch (Exception e) {
            rglog.error(e.getMessage());
            rglog.error("登记虚拟账户记账支付订单失败:<{}>", e);
        }

    }

    /*领取卡券*/
    void claimCoupon(List<MchntOrderInfo> mchntOrderInfoList) {
        if (!"00".equals(mchntOrderInfoList.get(0).getBizSceneType())) {
            return;
        }
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        DubboService dubboService = new DubboServiceImpl();
        String reserve = null;
        try {
            Header header = new Header();
            header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
            header.setSrcSysId(AppParamConstant.SYS_ID);
            header.setBizType("00");
            header.setTxnNum("P01MO001");
            header.setVersion("1.0.0");
            header.setTraceNo(mchntOrderInfoList.get(0).getSysSeqNum() + "0");
            header.setTransTime(DateUtil.getCurrentTime());
            header.setTransDate(DateUtil.getCurrentDate());
            ClaimCouponRequest claimCouponRequest = new ClaimCouponRequest();
            claimCouponRequest.setHeader(header);
            List<ClaimCouponMcInfoBean> mcInfoList = new ArrayList<>();
            for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
                ClaimCouponMcInfoBean claimCouponMcInfoBean = new ClaimCouponMcInfoBean();
                claimCouponMcInfoBean.setPurchaseAmt(mchntOrderInfo.getOrderAmt());
                claimCouponMcInfoBean.setClaimQuantity("1");
                reserve = mchntOrderInfo.getTermNo();
                if (reserve != null) {
                    String[] mcInfo = reserve.split("|");
                    claimCouponMcInfoBean.setRuleIndex(mcInfo[1]);
                    claimCouponMcInfoBean.setMcNo(mcInfo[0]);
                }
                claimCouponMcInfoBean.setClaimUser(mchntOrderInfo.getUserId());
                claimCouponMcInfoBean.setClaimType("4");
                claimCouponMcInfoBean.setCouponLockFlag("1");
                mcInfoList.add(claimCouponMcInfoBean);
            }
            claimCouponRequest.setMcInfoList(mcInfoList);
            int iReturnCode = dubboService.asynCallDubboService("couponManagementService", "claimCoupon", claimCouponRequest, "AsynClaimCouponService");
            if (iReturnCode != 0) {
                rglog.error("异步卡券领取服务注册失败！");
            }
        } catch (Exception e) {
            rglog.error(e.getMessage());
            rglog.error("异步卡券领取服务注册失败！");
        }

    }

    /**
     * 合并支付冲正-异步调用
     */
    void mompComboPayRevsal(List<MchntOrderInfo> mchntOrderInfoList, List<PayOrderInfo> payOrderInfoList) {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        if ("00".equals(mchntOrderInfoList.get(0).getBizSceneType())) {
            return;
        }
        DubboService dubboService = new DubboServiceImpl();
        String discountFlag = AppParamConstant.NO;
        for (MchntOrderInfo mchntOrderInfo : mchntOrderInfoList) {
            if (mchntOrderInfo.getCustomerMarketAmt() != null && AmountUtil.compare(mchntOrderInfo.getCustomerMarketAmt(), "0.00") != 0) {
                discountFlag = AppParamConstant.YES;
                break;
            }
            if (mchntOrderInfo.getMchntDiscountFee() != null && AmountUtil.compare(mchntOrderInfo.getMchntDiscountFee(), "0.00") != 0) {
                discountFlag = AppParamConstant.YES;
                break;
            }
        }
        if (AppParamConstant.NO.equals(discountFlag)) {
            rglog.error("支付未参与任何营销，不需要冲正");
            return;
        }
        try {
            List<PayOrderInfo> payOrderInfoListMomp = payOrderInfoList.stream().filter(item -> item.getMsgDstId().equals(ChannelEnum.MOMP.getChannelType())).collect(Collectors.toList());
            /*参与营销，异步调用营销冲正接口*/
            ComboPaymentReversalRequest comboPaymentRevsalRequest = new ComboPaymentReversalRequest();
            Header header = new Header();
            header.setChanlId(OpmsParamConstant.OPM_SYS_ID);
            header.setSrcSysId(AppParamConstant.SYS_ID);
            header.setBizType("00");
            header.setTxnNum("P02MO001");
            header.setVersion("1.0.0");
            header.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + "1");
            header.setTransTime(DateUtil.getCurrentTime());
            header.setTransDate(DateUtil.getCurrentDate());
            comboPaymentRevsalRequest.setOrigTraceNo(payOrderInfoListMomp.get(0).getChannelReconKey());
            comboPaymentRevsalRequest.setHeader(header);
            int iReturnCode = dubboService.asynCallDubboService("paymentService", "comboPaymentRevsal", comboPaymentRevsalRequest, "AsynComboPaymentRevsalService");
            if (iReturnCode != 0) {
                rglog.error("异步营销冲正服务注册失败！");
            }
        } catch (Exception e) {
            rglog.error(e.getMessage());
            rglog.error("异步营销退款失败！");
        }

    }

}
